home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / imlib / port / dos4gw / profile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-16  |  43.7 KB  |  1,565 lines

  1. /****************************************************************************
  2. *
  3. *  File              : profile.c
  4. *  Date Created      : 10/14/94
  5. *  Description       : 
  6. *
  7. *  Programmer(s)     : Nick Skrepetos
  8. *  Last Modification : 12/10/94 - 11:56:16 PM
  9. *  Additional Notes  :
  10. *
  11. *****************************************************************************
  12. *            Copyright (c) 1993-95,  HMI, Inc.  All Rights Reserved            *
  13. ****************************************************************************/
  14.  
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <dos.h>
  18. #include <fcntl.h> 
  19. #include <bios.h>
  20. #include <io.h>
  21. #include <malloc.h>
  22. #include <conio.h>
  23. #include <ctype.h>
  24. #include <string.h>
  25. #include "sos.h"
  26. #include "profile.h"
  27.  
  28. /****************************************************************************
  29.  
  30.    Possible Additions:
  31.  
  32.       hmiINIAddItemDecimal( )       adds new item w/decimal
  33.       hmiINIAddItemQuery( )         adds new item w/query Yes/No
  34.       hmiINIAddRawString( )         adds new raw string
  35.  
  36.    Error Checking:
  37.  
  38.       allow TABS to be skipped as "White Space" in addition to spaces so
  39.       that editors that use tabs will work also.
  40.  
  41.       allow String functions to support lists with comma (,) seperators
  42.       like the decimal functions do.
  43.  
  44.       allow location functions to be case sensitive or insensitive
  45.  
  46.       get rid of compiler dependent stuff like memcpy, stricmp
  47.  
  48. ****************************************************************************/
  49.  
  50. // local data
  51. static   PSTR  szHexNumbers  =  "0123456789ABCDEF";
  52. static   W32  wMultiplier[]   =  { 1, 16, 256, 4096, 65536, 1048576, 16777216, 268435456 };
  53.  
  54. // local function prototypes
  55. W32    hmiINIHex2Decimal    ( PSTR szHexValue );
  56. W32    hmiINIGetHexIndex    ( BYTE bValue );
  57.  
  58.  
  59. /****************************************************************************
  60. *
  61. *  Syntax
  62. *
  63. *     BOOL    cdecl hmiINIOpen( _INI_INSTANCE * sInstance, PSTR szName )
  64. *
  65. *  Description
  66. *
  67. *     opens and instance of a .ini file
  68. *
  69. *  Parameters
  70. *
  71. *        Type           Description
  72. *        --------------------------
  73. *        sInstance      pointer to an .ini instance
  74. *        szName         pointer to the name of the .ini file
  75. *
  76. *  Return
  77. *
  78. *     _TRUE       the file was opened correctly
  79. *     _FALSE      there was a problem opening the file
  80. *
  81. ****************************************************************************/
  82. BOOL    cdecl hmiINIOpen( _INI_INSTANCE * sInstance, PSTR szName )
  83.     {
  84.       W32  hFile;
  85.  
  86.       // save the name of the .ini file
  87.       strcpy( ( char * )sInstance->szName, ( char const * )szName );
  88.  
  89.       // open .ini file, return error if file is not
  90.       // found.
  91.       if ( ( hFile = open( szName, O_RDONLY | O_BINARY ) ) == -1 )
  92.          return( _FALSE );
  93.  
  94.       // determine size of file
  95.       sInstance->wSize  =  lseek( hFile, 0, SEEK_END );
  96.  
  97.       // set the new maximum size 
  98.       sInstance->wMaxSize  =  sInstance->wSize + _INI_EXTRA_MEMORY;
  99.  
  100.       // seek back to start of file
  101.       lseek( hFile, 0, SEEK_SET );
  102.  
  103.       // allocate memory for the file
  104.       if ( ( sInstance->pData  =  ( PSTR )malloc( sInstance->wMaxSize ) ) == _NULL )
  105.       {
  106.          // close file
  107.          close( hFile );
  108.  
  109.          // return error, not enough memory
  110.          return( _FALSE );
  111.       }
  112.  
  113.       // read in file
  114.       if ( read( hFile, sInstance->pData, sInstance->wSize ) != sInstance->wSize )
  115.       {
  116.          // close file
  117.          close( hFile );
  118.  
  119.          // free memory
  120.          free( sInstance->pData );
  121.  
  122.          // return error, not file size incorrect
  123.          return( _FALSE );
  124.       }
  125.  
  126.       // close file
  127.       close( hFile );
  128.  
  129.       // init current position
  130.       sInstance->pCurrent  =  sInstance->pData;
  131.       sInstance->wCurrent  =  0;
  132.  
  133.       // initalize current item pointer
  134.       sInstance->pItem     =  _NULL;
  135.       sInstance->pList     =  _NULL;
  136.       sInstance->pItemPtr  =  _NULL;
  137.       sInstance->pListPtr  =  _NULL;
  138.  
  139.       // reset the modified flag to indicate that the 
  140.       // file is unmodified.
  141.       sInstance->wFlags    &= ~_INI_MODIFIED;
  142.  
  143.       // return success
  144.       return( _TRUE );
  145.     }
  146.  
  147. /****************************************************************************
  148. *
  149. *  Syntax
  150. *
  151. *     BOOL    cdecl hmiINIClose( _INI_INSTANCE * sInstance )
  152. *
  153. *  Description
  154. *
  155. *     close and instance of a .ini file. note that if the file is modified
  156. *     it will be written back to the original file.
  157. *
  158. *  Parameters
  159. *
  160. *        Type           Description
  161. *        --------------------------
  162. *        sInstance      pointer to .ini instance
  163. *
  164. *  Return
  165. *
  166. *     _TRUE       file was closed and/or written correctly
  167. *     _FALSE      a problem was encountered when writing/closing the file
  168. *
  169. ****************************************************************************/
  170. BOOL    cdecl hmiINIClose( _INI_INSTANCE * sInstance )
  171.     {
  172.       W32  hFile;
  173.  
  174.       // determine if the .ini file has been modified
  175.       if ( sInstance->wFlags & _INI_MODIFIED )
  176.       {
  177.          // create and open file 
  178.          if ( ( hFile =  open( (const char * )sInstance->szName, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0 ) ) == -1 )
  179.          {
  180.               // free memory
  181.             free( sInstance->pData );
  182.  
  183.             // error creating file
  184.             return( _FALSE );
  185.          }
  186.  
  187.          // write data back out
  188.          write( hFile, sInstance->pData, sInstance->wSize );
  189.  
  190.          // close file
  191.          close( hFile );
  192.       }
  193.  
  194.         // free memory
  195.       free( sInstance->pData );
  196.  
  197.       // return success
  198.       return( _TRUE );
  199.     }
  200.  
  201.  
  202. /****************************************************************************
  203. *
  204. *  Syntax
  205. *
  206. *     BOOL cdecl  hmiINILocateSection( _INI_INSTANCE * sInstance, PSTR szName )
  207. *
  208. *  Description
  209. *
  210. *     locates a section in a file.  a section is determined by enclosing 
  211. *     it in [].  ie.  [SECTION]
  212. *
  213. *  Parameters
  214. *
  215. *        Type           Description
  216. *        --------------------------
  217. *        sInstance      pointer to .ini instance
  218. *        szName         pointer to section name
  219. *
  220. *  Return
  221. *
  222. *     _TRUE       section located
  223. *     _FALSE      section not located
  224. *
  225. ****************************************************************************/
  226. BOOL  cdecl hmiINILocateSection( _INI_INSTANCE * sInstance, PSTR szName )
  227.     {
  228.       PSTR  pDataPtr;
  229.       PSTR    pSectionPtr;
  230.       PSTR  szSection;
  231.       W32  wIndex;
  232.       W32  wFoundFlag  =  _FALSE;
  233.  
  234.       // set data pointer to pointer to start of .ini in memory
  235.       pDataPtr    =  sInstance->pData;
  236.  
  237.       // initialize index
  238.       wIndex      =  0;
  239.  
  240.       // search data until we have found a start section character
  241.       // and then attempt to match section string.  continue to process
  242.       // entire data set until the end is reached or a match is 
  243.       // found.
  244.       do
  245.          {
  246.             // check if character we are pointing to is a 
  247.             // start section character
  248.             if ( *pDataPtr == _INI_SECTION_START )
  249.             {
  250.                // save pointer to start of section for use by the
  251.                // delete functions.
  252.                pSectionPtr =  pDataPtr;
  253.  
  254.                // advance past the start section character
  255.                pDataPtr++;
  256.  
  257.                // set pointer to section name
  258.                szSection   =  szName;
  259.  
  260.                // search the string character by character to determine
  261.                // if we have a match.
  262.                while( *pDataPtr == *szSection && wIndex < sInstance->wSize )
  263.                {
  264.                   // advance section pointer
  265.                   szSection++;
  266.  
  267.                   // advance data pointer
  268.                   pDataPtr++;
  269.  
  270.                   // advance data index
  271.                   wIndex++;
  272.                }
  273.  
  274.                // determine if we are sitting on a end section 
  275.                // character. if so then we have a complete match
  276.                // so set the found flag to true.
  277.                if ( *pDataPtr == _INI_SECTION_END && *szSection == _NULL )
  278.                {
  279.                   // set found flag
  280.                   wFoundFlag  =  _TRUE;
  281.  
  282.                   // move to the next line
  283.                   while( *pDataPtr != _INI_LF )
  284.                      pDataPtr++;
  285.  
  286.                   // advance past line feed
  287.                   pDataPtr++;
  288.  
  289.                   // set list pointer for raw name
  290.                   sInstance->pListPtr  =  pDataPtr;
  291.  
  292.                   // set current data pointer to new section
  293.                   // location.
  294.                   sInstance->pCurrent  =  pDataPtr;
  295.                   sInstance->wCurrent  =  wIndex;
  296.  
  297.                   // save pointer to start of current section for
  298.                   // use by other functions.
  299.                   sInstance->pSection  =  pSectionPtr;
  300.                }
  301.  
  302.             }
  303.  
  304.             // advance pointer 
  305.             pDataPtr++;
  306.  
  307.             // advance index
  308.             wIndex++;
  309.          }
  310.       while( !wFoundFlag && wIndex < sInstance->wSize );
  311.  
  312.       // return the status of the found flag, this will indicate
  313.       // if the desired section was located.
  314.       return( ( BOOL )wFoundFlag );
  315.     }
  316.  
  317.  
  318. /****************************************************************************
  319. *
  320. *  Syntax
  321. *
  322. *     BOOL    cdecl hmiINILocateItem( _INI_INSTANCE * sInstance, PSTR szItem )
  323. *
  324. *  Description
  325. *
  326. *     locates an item under a section in an .ini file
  327. *
  328. *  Parameters
  329. *
  330. *        Type           Description
  331. *        --------------------------
  332. *        sInstance      pointer to an .ini instance
  333. *        szItem         pointer to the name of the item
  334. *
  335. *  Return
  336. *
  337. *     _TRUE    the item was located
  338. *     _FALSE   the item was not located
  339. *
  340. ****************************************************************************/
  341. BOOL    cdecl hmiINILocateItem( _INI_INSTANCE * sInstance, PSTR szItem )
  342.     {
  343.       PSTR  pDataPtr;
  344.       PSTR  pItemPtr;
  345.       PSTR  szSearch;
  346.       W32  wIndex;
  347.       W32  wFoundFlag  =  _FALSE;
  348.  
  349.       // initialize current location pointers
  350.       pDataPtr =  sInstance->pCurrent;
  351.       wIndex   =  sInstance->wCurrent;
  352.  
  353.       // search each data item until match is found or the start
  354.       // of a new section is found
  355.       do
  356.          {
  357.             // set up search pointer
  358.             szSearch =  szItem;
  359.  
  360.             // check if current character matches first
  361.             // character of search string
  362.             if ( *pDataPtr == *szSearch )
  363.             {
  364.                // set pointer to start of potential item.  this pointer
  365.                // will be used later to mark the start of the item
  366.                // string.
  367.                pItemPtr    =  pDataPtr;
  368.  
  369.                // advance data pointer and search pointer
  370.                pDataPtr++;
  371.                szSearch++;
  372.  
  373.                // advance search index
  374.                wIndex++;
  375.  
  376.                // search the rest of the string, make sure we do not overrun
  377.                // the end of file and that the string still matches.
  378.                while( *pDataPtr == *szSearch && wIndex < sInstance->wSize )
  379.                {
  380.                   // advance data pointer
  381.                   pDataPtr++;
  382.  
  383.                   // advance search pointer
  384.                   szSearch++;
  385.  
  386.                   // advance index
  387.                   wIndex++;
  388.                }
  389.  
  390.                // check if we located the string
  391.                if ( *szSearch == _NULL )
  392.                {
  393.                   // skip any white until we locate the '='
  394.                   // sign.
  395.                   while( *pDataPtr != _INI_EQUATE && *pDataPtr != _INI_EOL )
  396.                   {
  397.                      // advance data pointer
  398.                      pDataPtr++;
  399.  
  400.                      // advance index
  401.                      wIndex++;
  402.                   }
  403.  
  404.                   // check if we found and equate '=' character, if not
  405.                   // only set the start of line indicator so the string
  406.                   // and decimal routines know there is no value.
  407.                   if ( *pDataPtr == _INI_EQUATE )
  408.                   {
  409.                      // advance data pointer one past the equate
  410.                      pDataPtr++;
  411.  
  412.                      // advance index
  413.                      wIndex++;
  414.  
  415.                      // set the pointer to the new item
  416.                      sInstance->pItem     =  pDataPtr;
  417.                   }
  418.                   else
  419.                      sInstance->pItem     =  _NULL;
  420.  
  421.                   // set the start of line item pointer for later use
  422.                   sInstance->pItemPtr  =  pItemPtr;
  423.  
  424.                   // reset list pointer to indicate that we
  425.                   // do not have a list yet.
  426.                   sInstance->pList  =  _NULL;
  427.  
  428.                   // set the found flag
  429.                   wFoundFlag  =  _TRUE;
  430.                }
  431.             }
  432.  
  433.             // advance to next place in data
  434.             pDataPtr++;
  435.  
  436.             // advance index
  437.             wIndex++;
  438.          }
  439.       while( !wFoundFlag && wIndex < sInstance->wSize && *pDataPtr != _INI_SECTION_START );
  440.  
  441.       // return found flag status
  442.       return( ( BOOL )wFoundFlag );
  443.     }
  444.  
  445.  
  446. /****************************************************************************
  447. *
  448. *  Syntax
  449. *
  450. *     BOOL    cdecl hmiINIGetDecimal( _INI_INSTANCE * sInstance, W32 * wValue )
  451. *
  452. *  Description
  453. *
  454. *     retrieves a decimal value from an item in a .ini file.  note that if
  455. *     the value is in hex (0x....) it will be automatically converted to 
  456. *     decimal.
  457. *
  458. *  Parameters
  459. *
  460. *        Type           Description
  461. *        --------------------------
  462. *        sInstance      pointer to an .ini instance
  463. *        wValue         pointer to a word to store decimal value in
  464. *
  465. *  Return
  466. *
  467. *     _TRUE    value was located and converted correctly
  468. *     _FALSE   value was not valid, or item search was not performed
  469. *
  470. ****************************************************************************/
  471. BOOL    cdecl hmiINIGetDecimal( _INI_INSTANCE * sInstance, W32 * wValue )
  472.     {
  473.       PSTR  pDataPtr;
  474.         W32  wDValue;
  475.       BYTE  bBuffer[ 32 ];
  476.       W32  wIndex;
  477.  
  478.       // initialize pointer to data
  479.       if ( sInstance->pList )
  480.          pDataPtr    =  sInstance->pList;
  481.       else
  482.          pDataPtr    =  sInstance->pItem;
  483.  
  484.       // check if it is null
  485.       if ( pDataPtr == _NULL )
  486.          return( _FALSE );
  487.  
  488.       // skip all white space
  489.       while( *pDataPtr == _INI_SPACE )
  490.          pDataPtr++;
  491.  
  492.       // check if we are pointing to and EOL
  493.       if ( *pDataPtr == _INI_EOL )
  494.          return( _FALSE );
  495.  
  496.       // initialize buffer index
  497.       wIndex   =  0;
  498.  
  499.       // fetch string for value
  500.       while( *pDataPtr != _INI_EOL && *pDataPtr != _INI_LIST_SEPERATOR 
  501.                && *pDataPtr != _INI_SPACE )
  502.       {
  503.          // save character
  504.          bBuffer[ wIndex++ ]  =  *pDataPtr++;
  505.       }
  506.  
  507.       // set null at the end of buffer
  508.       bBuffer[ wIndex ]       =  '\0';
  509.  
  510.       // check if we have simply reached the end of the
  511.       // line with no number.
  512.       if ( wIndex == 0 )
  513.          return( _FALSE );
  514.  
  515.       // skip all white space
  516.       while( *pDataPtr == _INI_SPACE )
  517.          pDataPtr++;
  518.  
  519.       // check if we have a list of numbers
  520.       if ( *pDataPtr == _INI_LIST_SEPERATOR )
  521.       {
  522.          // set list pointer to one past the current
  523.          // seperator.
  524.          sInstance->pList  =  ++pDataPtr;
  525.       }
  526.       else
  527.          sInstance->pList  =  pDataPtr;
  528.  
  529.       // check if the buffer contains a hex value
  530.       if ( bBuffer[ 1 ] == _INI_HEX_INDICATOR )
  531.       {
  532.          // fetch hex value
  533.          wDValue  =  hmiINIHex2Decimal( ( char near * )&bBuffer[ 2 ] );
  534.       }
  535.       else
  536.       {
  537.          // fetch value
  538.          wDValue  =  (W32)atoi( ( const char * )bBuffer );
  539.       }
  540.  
  541.       // set value
  542.       *wValue  =  wDValue;
  543.  
  544.       // return status
  545.       return( _TRUE );
  546.     }
  547.  
  548.  
  549. /****************************************************************************
  550. *
  551. *  Syntax
  552. *
  553. *     BOOL    cdecl hmiINIGetString( _INI_INSTANCE * sInstance, PSTR pString, W32 wMaxLength )
  554. *
  555. *  Description
  556. *
  557. *     fetches string from .ini file
  558. *
  559. *  Parameters
  560. *
  561. *        Type           Description
  562. *        --------------------------
  563. *        sInstance      pointer to .ini instance
  564. *        pString        pointer to store string
  565. *        wMaxLength     maximum length of string to fetch
  566. *
  567. *  Return
  568. *
  569. *     _TRUE    string was returned correctly
  570. *     _FALSE   item search was not performed before calling this function
  571. *
  572. ****************************************************************************/
  573. BOOL    cdecl hmiINIGetString( _INI_INSTANCE * sInstance, PSTR pString, W32 wMaxLength )
  574.     {
  575.       PSTR  pDataPtr;
  576.       W32  wIndex;
  577.  
  578.       // initialize pointer to data
  579.       if ( sInstance->pList )
  580.          pDataPtr    =  sInstance->pList;
  581.       else
  582.          pDataPtr    =  sInstance->pItem;
  583.  
  584.       // check if it is null
  585.       if ( pDataPtr == _NULL )
  586.          return( _FALSE );
  587.  
  588.       // initialize index
  589.       wIndex   =  0;
  590.  
  591.       // find start of string, first non-space character
  592.       while( *pDataPtr  == _INI_SPACE )
  593.          pDataPtr++;
  594.  
  595.       // copy string into buffer
  596.       while( *pDataPtr != _INI_EOL && *pDataPtr != _INI_LIST_SEPERATOR && wIndex < wMaxLength - 1 )
  597.          pString[ wIndex++ ] =  *pDataPtr++;
  598.  
  599.       // place a _NULL at the end of the string
  600.       pString[ wIndex ] =  '\0';
  601.  
  602.       // if we have reached maximum buffer length, search until
  603.       // we get to the EOL or list seperator
  604.       if ( wIndex == wMaxLength - 1 )
  605.       {
  606.          // find end / list seperator
  607.          while( *pDataPtr != _INI_EOL && *pDataPtr != _INI_LIST_SEPERATOR )
  608.             pDataPtr++;
  609.       }
  610.  
  611.       // check if we have a list of items
  612.       if ( *pDataPtr == _INI_LIST_SEPERATOR )
  613.       {
  614.          // set list pointer to one past the current
  615.          // seperator.
  616.          sInstance->pList  =  ++pDataPtr;
  617.       }
  618.       else
  619.          sInstance->pList  =  pDataPtr;
  620.  
  621.       // return success
  622.       return( _TRUE );
  623.     }
  624.  
  625. /****************************************************************************
  626. *
  627. *  Syntax
  628. *
  629. *     BOOL    cdecl hmiINIGetRawString( _INI_INSTANCE * sInstance, PSTR pString, W32 wMaxLength )
  630. *
  631. *  Description
  632. *
  633. *     fetches string from .ini file
  634. *
  635. *  Parameters
  636. *
  637. *        Type           Description
  638. *        --------------------------
  639. *        sInstance      pointer to .ini instance
  640. *        pString        pointer to store string
  641. *        wMaxLength     maximum length of string to fetch
  642. *
  643. *  Return
  644. *
  645. *     _TRUE    string was returned correctly
  646. *     _FALSE   end of strings to fetch, or no section locate performed
  647. *
  648. ****************************************************************************/
  649. BOOL    cdecl hmiINIGetRawString( _INI_INSTANCE * sInstance, PSTR pString, W32 wMaxLength )
  650.     {
  651.       PSTR  pDataPtr;
  652.       PSTR  pEOFPtr;
  653.       W32  wIndex;
  654.  
  655.       // initialize data pointer
  656.       pDataPtr =  sInstance->pListPtr;
  657.  
  658.       // check if it is null
  659.       if ( pDataPtr == _NULL || *pDataPtr == _INI_SECTION_START ||
  660.             *pDataPtr   == _INI_EOL )
  661.          return( _FALSE );
  662.  
  663.       // determine EOF pointer
  664.       pEOFPtr  =  sInstance->pData + sInstance->wSize;
  665.  
  666.       // initialize index
  667.       wIndex   =  0;
  668.  
  669.       // find start of string, first non-space character
  670.       while( *pDataPtr  == _INI_SPACE )
  671.          pDataPtr++;
  672.  
  673.       // copy string into buffer
  674.       while( *pDataPtr != _INI_EOL && wIndex < wMaxLength - 1 )
  675.          pString[ wIndex++ ] =  *pDataPtr++;
  676.  
  677.       // place a _NULL at the end of the string
  678.       pString[ wIndex ] =  '\0';
  679.  
  680.       // skip past end of line
  681.       pDataPtr += 2;
  682.  
  683.       // make sure we are not at the end of the
  684.       // file.
  685.       if ( pDataPtr >= pEOFPtr )
  686.          sInstance->pListPtr  =  _NULL;
  687.       else
  688.          // save off current position
  689.          sInstance->pListPtr  =  pDataPtr;
  690.  
  691.       // return success
  692.       return( _TRUE );
  693.     }
  694.  
  695. /****************************************************************************
  696. *
  697. *  Syntax
  698. *
  699. *     BOOL    cdecl hmiINIWriteDecimal( _INI_INSTANCE * sInstance, W32 wValue )
  700. *
  701. *  Description
  702. *
  703. *     writes decimal value to .ini item
  704. *
  705. *  Parameters
  706. *
  707. *        Type           Description
  708. *        --------------------------
  709. *        sInstance      pointer to an .ini instance
  710. *        wValue         value to write out
  711. *
  712. *  Return
  713. *
  714. *     _TRUE    value written correctly
  715. *     _FALSE   value not written correctly
  716. *
  717. ****************************************************************************/
  718. BOOL    cdecl hmiINIWriteDecimal( _INI_INSTANCE * sInstance, W32 wValue )
  719.     {
  720.       PSTR  pDataPtr;
  721.       PSTR  pValuePtr;
  722.       BYTE  bBuffer[ 32 ];
  723.       W32  wIndex;
  724.       W32  wStringSize;
  725.       W32  wDecimalSize;
  726.       W32  wMoveSize;
  727.  
  728.       // check if item was previously located
  729.       if ( sInstance->pItem == _NULL )
  730.          return( _FALSE );
  731.  
  732.       // get pointer to item
  733.       pDataPtr =  sInstance->pItem;
  734.  
  735.       // skip all white space
  736.       while( *pDataPtr == _INI_SPACE )
  737.          pDataPtr++;
  738.  
  739.       // save pointer to value location
  740.       pValuePtr   =  pDataPtr;
  741.  
  742.       // initialize string length
  743.       wStringSize =  0;
  744.  
  745.       // fetch string for value
  746.       while( *pDataPtr != _INI_EOL )
  747.       {
  748.          // save character and advance string size
  749.          bBuffer[ wStringSize++ ]   =  *pDataPtr++;
  750.       }
  751.  
  752.       // set null at the end of buffer
  753.       bBuffer[ wStringSize ]  =  '\0';
  754.  
  755.       // check if the buffer contains a hex value
  756.       if ( bBuffer[ 1 ] == _INI_HEX_INDICATOR )
  757.       {
  758.          // convert value to hex string
  759.          itoa( wValue, ( char * )&bBuffer[ 2 ], 16 );
  760.       }
  761.       else
  762.       {
  763.            // convert value to decimal string
  764.          itoa( wValue, ( char * )&bBuffer[ 0 ], 10 );
  765.       }
  766.  
  767.       // get length of converted string
  768.       wDecimalSize   =  strlen( ( const char * )bBuffer );
  769.  
  770.       // check if we need to shrink or expand the 
  771.       // data size.
  772.       if ( wDecimalSize < wStringSize )
  773.       {
  774.          // calculate the move size
  775.          wMoveSize   =  ( ( sInstance->pData + sInstance->wSize ) - pValuePtr ) - ( wStringSize - wDecimalSize );
  776.  
  777.          // need to shrink the size of the .ini file
  778.          memmove( pValuePtr, pValuePtr + ( wStringSize - wDecimalSize ), wMoveSize );
  779.  
  780.          // adjust size
  781.          sInstance->wSize  -= ( wStringSize - wDecimalSize );
  782.       }
  783.       else
  784.          // check if expand data
  785.          if ( wDecimalSize > wStringSize )
  786.          {
  787.             // make sure we have enough memory to expand
  788.             if ( sInstance->wSize + ( wDecimalSize - wStringSize ) > sInstance->wMaxSize )
  789.                return( _FALSE );
  790.  
  791.             // need to expand the size of the .ini file,
  792.             // calculate the move size
  793.             wMoveSize   =  ( ( sInstance->pData + sInstance->wSize ) - pValuePtr ) + ( wDecimalSize - wStringSize );
  794.  
  795.             // need to shrink the size of the .ini file
  796.             memmove( pValuePtr + ( wDecimalSize - wStringSize ), pValuePtr, wMoveSize );
  797.  
  798.             // adjust size
  799.             sInstance->wSize  += ( wDecimalSize - wStringSize );
  800.          }
  801.  
  802.       // initialize index
  803.       wIndex      =  0;
  804.  
  805.       // copy in new string
  806.       while( bBuffer[ wIndex ] )
  807.          *pValuePtr++   =  bBuffer[ wIndex++ ];
  808.  
  809.       // set the modified flag
  810.       sInstance->wFlags    |= _INI_MODIFIED;
  811.  
  812.       // return success
  813.       return( _TRUE );
  814.     }
  815.  
  816. /****************************************************************************
  817. *
  818. *  Syntax
  819. *
  820. *     BOOL    cdecl hmiINIWriteString( _INI_INSTANCE * sInstance, PSTR szString )
  821. *
  822. *  Description
  823. *
  824. *     writes out string to item
  825. *
  826. *  Parameters
  827. *
  828. *        Type           Description
  829. *        --------------------------
  830. *        sInstance      pointer to an .ini instance
  831. *        szString       null terminated string
  832. *
  833. *  Return
  834. *
  835. *     _TRUE    the string was written correctly
  836. *     _FALSE   the string was not written correctly
  837. *
  838. ****************************************************************************/
  839. BOOL    cdecl hmiINIWriteString( _INI_INSTANCE * sInstance, PSTR szString )
  840.     {
  841.       PSTR  pDataPtr;
  842.       PSTR  pStringPtr;
  843.       W32  wMoveSize;
  844.       W32  wSourceSize;
  845.       W32  wDestSize;
  846.  
  847.       // initialize data pointer
  848.       pDataPtr =  sInstance->pItem;
  849.  
  850.       // check if it is null
  851.       if ( pDataPtr == _NULL )
  852.          return( _FALSE );
  853.  
  854.       // initialize destination length
  855.       wDestSize   =  0;
  856.  
  857.       // find start of string character, first non-space
  858.       // character.
  859.       while( *pDataPtr  == _INI_SPACE )
  860.          pDataPtr++;
  861.  
  862.       // save place to store new string
  863.       pStringPtr  =  pDataPtr;
  864.  
  865.       // copy string into buffer
  866.       while( *pDataPtr++ != _INI_EOL )
  867.          wDestSize++;
  868.  
  869.       // get string length of new string
  870.       wSourceSize    =  strlen( szString );
  871.  
  872.       // check if we need to shrink or expand the 
  873.       // data size.
  874.       if ( wSourceSize < wDestSize )
  875.       {
  876.          // calculate the move size
  877.          wMoveSize   =  ( ( sInstance->pData + sInstance->wSize ) - pStringPtr ) - ( wDestSize - wSourceSize );
  878.  
  879.          // need to shrink the size of the .ini file
  880.          memmove( pStringPtr, pStringPtr + ( wDestSize - wSourceSize ), wMoveSize );
  881.  
  882.          // adjust size
  883.          sInstance->wSize  -= ( wDestSize - wSourceSize );
  884.       }
  885.       else
  886.          // check if expand data
  887.          if ( wSourceSize > wDestSize )
  888.          {
  889.             // make sure we have enough memory to expand
  890.             if ( sInstance->wSize + ( wSourceSize - wDestSize ) > sInstance->wMaxSize )
  891.                return( _FALSE );
  892.  
  893.             // need to expand the size of the .ini file,
  894.             // calculate the move size
  895.             wMoveSize   =  ( ( sInstance->pData + sInstance->wSize ) - pStringPtr ) + ( wSourceSize - wDestSize );
  896.  
  897.             // need to shrink the size of the .ini file
  898.             memmove( pStringPtr + ( wSourceSize - wDestSize ), pStringPtr, wMoveSize );
  899.  
  900.             // adjust size
  901.             sInstance->wSize  += ( wSourceSize - wDestSize );
  902.          }
  903.  
  904.       // copy in new string
  905.       while( *szString )
  906.          *pStringPtr++   =  *szString++;
  907.  
  908.       // set the modified flag
  909.       sInstance->wFlags    |= _INI_MODIFIED;
  910.  
  911.       // return success
  912.       return( _TRUE );
  913.     }
  914.  
  915. /****************************************************************************
  916. *
  917. *  Syntax
  918. *
  919. *     BOOL    cdecl hmiINIGetQuery( _INI_INSTANCE * sInstance, PSTR szItem )
  920. *
  921. *  Description
  922. *
  923. *     get a Yes/No type answer from item
  924. *
  925. *  Parameters
  926. *
  927. *        Type           Description
  928. *        --------------------------
  929. *        sInstance      pointer to an .ini instance
  930. *        szItem         pointer to item to locate in query
  931. *
  932. *  Return
  933. *
  934. *     _TRUE    "Yes" was found
  935. *     _FALSE   "No" or other was found
  936. *
  937. ****************************************************************************/
  938. BOOL    cdecl hmiINIGetQuery( _INI_INSTANCE * sInstance, PSTR szItem )
  939.     {
  940.         BYTE  bBuffer[ 32 ];
  941.  
  942.       // locate item within section
  943.       if ( !hmiINILocateItem( sInstance, szItem ) )
  944.          return( _FALSE );
  945.  
  946.       // get string from .ini file
  947.       if ( !hmiINIGetString( sInstance, ( char near * )bBuffer, 32 ) )
  948.          return( _FALSE );
  949.  
  950.       // compare string to "Yes"
  951.       if ( strcmpi( ( char const * )bBuffer, ( char const * )"YES" ) == 0 )
  952.          return( _TRUE );
  953.       else
  954.          return( _FALSE );
  955.     }
  956.  
  957. /****************************************************************************
  958. *
  959. *  Syntax
  960. *
  961. *     BOOL    cdecl hmiINIGetItemDecimal( _INI_INSTANCE * sInstance, PSTR szItem, 
  962. *                                       W32 * wValue )
  963. *
  964. *  Description
  965. *
  966. *     locates and item and returns the decimal value associated with it
  967. *
  968. *  Parameters
  969. *
  970. *        Type           Description
  971. *        --------------------------
  972. *        sInstance      pointer to .ini instance
  973. *        szItem         pointer to item string
  974. *        wValue         pointer to word value 
  975. *
  976. *  Return
  977. *
  978. *     _TRUE       value located and retrieved
  979. *     _FALSE      error getting value
  980. *
  981. ****************************************************************************/
  982. BOOL    cdecl hmiINIGetItemDecimal( _INI_INSTANCE * sInstance, PSTR szItem, 
  983.                                   W32 * wValue )
  984.     {
  985.       // attempt to locate item
  986.       if ( !hmiINILocateItem( sInstance, szItem ) )
  987.          return( _FALSE );
  988.  
  989.       // get decimal value
  990.       if ( !hmiINIGetDecimal( sInstance, wValue ) )
  991.          return( _FALSE );
  992.  
  993.       // return success
  994.       return( _TRUE );
  995.     }
  996.  
  997. /****************************************************************************
  998. *
  999. *  Syntax
  1000. *
  1001. *     BOOL    cdecl    hmiINIGetItemString( _INI_INSTANCE * sInstance, PSTR szItem,
  1002. *                                      PSTR  pString, W32 wMaxSize )
  1003. *
  1004. *  Description
  1005. *
  1006. *     locates item and retrieves string associated with it
  1007. *
  1008. *  Parameters
  1009. *
  1010. *        Type           Description
  1011. *        --------------------------
  1012. *        sInstance      pointer to an .ini instance
  1013. *        szItem         pointer to item string
  1014. *        pString        pointer to string data area
  1015. *        wMaxSize       maximum size of the string to get
  1016. *
  1017. *  Return
  1018. *
  1019. *     _TRUE       string retrieved
  1020. *     _FALSE      error retrieving string
  1021. *
  1022. ****************************************************************************/
  1023. BOOL    cdecl    hmiINIGetItemString( _INI_INSTANCE * sInstance, PSTR  szItem,
  1024.                                  PSTR  pString, W32  wMaxSize )
  1025.     {
  1026.       // attempt to locate the item string
  1027.         if ( !hmiINILocateItem( sInstance, szItem ) )
  1028.          return( _FALSE );
  1029.  
  1030.       // attempt to get string
  1031.       if ( !hmiINIGetString( sInstance, pString, wMaxSize ) )
  1032.          return( _FALSE );
  1033.  
  1034.       // return success
  1035.       return( _TRUE );
  1036.     }
  1037.  
  1038. /****************************************************************************
  1039. *
  1040. *  Syntax
  1041. *
  1042. *     BOOL    cdecl hmiINIWriteQuery( _INI_INSTANCE * sInstance, PSTR szItem, BOOL    wState )
  1043. *
  1044. *  Description
  1045. *
  1046. *     write a Yes/No type answer to an item
  1047. *
  1048. *  Parameters
  1049. *
  1050. *        Type           Description
  1051. *        --------------------------
  1052. *        sInstance      pointer to an .ini instance
  1053. *        szItem         pointer to item to alter
  1054. *        wState         flag: _TRUE or _FALSE
  1055. *
  1056. *  Return
  1057. *
  1058. *     _TRUE    query was modified
  1059. *     _FALSE   query was not modified
  1060. *
  1061. ****************************************************************************/
  1062. BOOL    cdecl hmiINIWriteQuery( _INI_INSTANCE * sInstance, PSTR szItem, BOOL    wState )
  1063.     {
  1064.       // locate item within section
  1065.       if ( !hmiINILocateItem( sInstance, szItem ) )
  1066.          return( _FALSE );
  1067.  
  1068.       // write string to .ini file
  1069.       if ( wState )
  1070.       {
  1071.          // write string
  1072.          if ( !hmiINIWriteString( sInstance, "Yes" ) )
  1073.             return( _FALSE );
  1074.       }
  1075.       else
  1076.       {
  1077.          // write string
  1078.          if ( !hmiINIWriteString( sInstance, "No" ) )
  1079.             return( _FALSE );
  1080.       }
  1081.  
  1082.       // return success
  1083.       return( _TRUE );
  1084.     }
  1085.  
  1086. /****************************************************************************
  1087. *
  1088. *  Syntax
  1089. *
  1090. *     BOOL    cdecl hmiINIDeleteItem( _INI_INSTANCE * sInstance, PSTR szItem )
  1091. *
  1092. *  Description
  1093. *
  1094. *     removes and item from within a section
  1095. *
  1096. *  Parameters
  1097. *
  1098. *        Type           Description
  1099. *        --------------------------
  1100. *        sInstance      pointer to and .ini instance
  1101. *        szItem         pointer to item string to remove
  1102. *
  1103. *  Return
  1104. *
  1105. *     _TRUE       item was found and removed
  1106. *     _FALSE      item was not located
  1107. *
  1108. ****************************************************************************/
  1109. BOOL    cdecl hmiINIDeleteItem( _INI_INSTANCE * sInstance, PSTR szItem )
  1110.     {
  1111.       PSTR  pDataPtr;
  1112.       W32  wStrSize =  0;
  1113.  
  1114.       // locate item within section
  1115.       if ( !hmiINILocateItem( sInstance, szItem ) )
  1116.          return( _FALSE );
  1117.  
  1118.       // get pointer to data
  1119.       pDataPtr =  sInstance->pItemPtr;
  1120.  
  1121.       // now find the length of the string to delete
  1122.       while( *(pDataPtr + wStrSize ) != _INI_LF )
  1123.          wStrSize++;
  1124.  
  1125.       // add one to size to include line feed
  1126.       wStrSize++;
  1127.  
  1128.       // perform memory move to delete string
  1129.       memmove( pDataPtr, pDataPtr + wStrSize, ( sInstance->pData + sInstance->wSize ) - ( pDataPtr + wStrSize ) );
  1130.  
  1131.       // adjust size of .ini file
  1132.       sInstance->wSize  -=    wStrSize;
  1133.  
  1134.       // set the modified flag
  1135.       sInstance->wFlags    |= _INI_MODIFIED;
  1136.  
  1137.         // return success
  1138.       return( _TRUE );
  1139.     }
  1140.  
  1141. /****************************************************************************
  1142. *
  1143. *  Syntax
  1144. *
  1145. *     BOOL    cdecl hmiINIDeleteSection( _INI_INSTANCE * sInstance, PSTR szSection )
  1146. *
  1147. *  Description
  1148. *
  1149. *     removes and item from within a section
  1150. *
  1151. *  Parameters
  1152. *
  1153. *        Type           Description
  1154. *        --------------------------
  1155. *        sInstance      pointer to and .ini instance
  1156. *        szSection      pointer to section to remove
  1157. *
  1158. *  Return
  1159. *
  1160. *     _TRUE       section was found and removed
  1161. *     _FALSE      section was not located
  1162. *
  1163. ****************************************************************************/
  1164. BOOL    cdecl hmiINIDeleteSection( _INI_INSTANCE * sInstance, PSTR szSection )
  1165.     {
  1166.       PSTR  pDataPtr;
  1167.       PSTR  pEOFPtr;
  1168.       W32  wSize;
  1169.  
  1170.       // locate item within section
  1171.       if ( !hmiINILocateSection( sInstance, szSection ) )
  1172.          return( _FALSE );
  1173.  
  1174.       // get pointer to data
  1175.       pDataPtr =  sInstance->pSection;
  1176.  
  1177.       // set end of file pointer
  1178.       pEOFPtr  =  sInstance->pData  +  sInstance->wSize;
  1179.  
  1180.       // advance szie one past section start to find the start of either the
  1181.       // next section or the end of file.
  1182.       wSize =  1;
  1183.  
  1184.       // now find the length of the string to delete
  1185.       while( *(pDataPtr + wSize ) != _INI_SECTION_START && ( pDataPtr + wSize ) < pEOFPtr )
  1186.          wSize++;
  1187.  
  1188.       // perform memory move to delete string
  1189.       memmove( pDataPtr, pDataPtr + wSize, pEOFPtr - ( pDataPtr + wSize ) );
  1190.  
  1191.       // adjust size of .ini file
  1192.       sInstance->wSize  -=    wSize;
  1193.  
  1194.       // set the modified flag
  1195.       sInstance->wFlags    |= _INI_MODIFIED;
  1196.  
  1197.         // return success
  1198.       return( _TRUE );
  1199.     }
  1200.  
  1201. /****************************************************************************
  1202. *
  1203. *  Syntax
  1204. *
  1205. *     BOOL    cdecl hmiINIAddSection( _INI_INSTANCE * sInstance, PSTR szSection )
  1206. *
  1207. *  Description
  1208. *
  1209. *     adds new section [...] to end of current file
  1210. *
  1211. *  Parameters
  1212. *
  1213. *        Type           Description
  1214. *        --------------------------
  1215. *        sInstance      pointer to an .ini instance
  1216. *        szSection      pointer to name of section to add
  1217. *
  1218. *  Return
  1219. *
  1220. *     _TRUE    section added to end of file
  1221. *     _FALSE   not enough memory to add new section or section exists
  1222. *
  1223. ****************************************************************************/
  1224. BOOL    cdecl hmiINIAddSection( _INI_INSTANCE * sInstance, PSTR szSection )
  1225.     {
  1226.       PSTR  pDataPtr;
  1227.       W32  wSize;
  1228.  
  1229.       // check if section exists
  1230.       if ( hmiINILocateSection( sInstance, szSection ) )
  1231.          return( _FALSE );
  1232.  
  1233.       // get pointer to end of file
  1234.       pDataPtr =  sInstance->pData + sInstance->wSize;
  1235.  
  1236.       // get size of new section name to add, plus
  1237.       // 8 to account for the CR/LF, start, end, CR/LF
  1238.       wSize =  strlen( szSection ) + 6;
  1239.  
  1240.       // check if there is room to add section
  1241.       if ( sInstance->wSize + wSize > sInstance->wMaxSize )
  1242.          return( _FALSE );
  1243.  
  1244.       // add CR/LF @ the end of the file
  1245.       *pDataPtr++ =  _INI_CR;
  1246.       *pDataPtr++ =  _INI_LF;
  1247.  
  1248.       // set current section pointer to here
  1249.       sInstance->pSection  =  pDataPtr;
  1250.  
  1251.       // copy in string start
  1252.       *pDataPtr++ =  _INI_SECTION_START;
  1253.  
  1254.       // copy in string
  1255.       while( *szSection )
  1256.          *pDataPtr++ =  *szSection++;
  1257.  
  1258.       // copy in string end
  1259.       *pDataPtr++ =  _INI_SECTION_END;
  1260.         
  1261.       // add CR/LF @ the end of the file
  1262.       *pDataPtr++ =  _INI_CR;
  1263.       *pDataPtr++ =  _INI_LF;
  1264.  
  1265.       // set section list pointer to here
  1266.       sInstance->pListPtr  =  pDataPtr;
  1267.  
  1268.       // set current pointer to here
  1269.       sInstance->pCurrent  =  pDataPtr;
  1270.  
  1271.       // adjust size
  1272.       sInstance->wSize     += wSize;
  1273.  
  1274.       // set the modified flag
  1275.       sInstance->wFlags    |= _INI_MODIFIED;
  1276.  
  1277.       // return success
  1278.       return( _TRUE );
  1279.  
  1280.     }
  1281.  
  1282. /****************************************************************************
  1283. *
  1284. *  Syntax
  1285. *
  1286. *     BOOL    cdecl    hmiINIAddItemString( _INI_INSTANCE * sInstance, PSTR szItem, 
  1287. *                                      PSTR szString, W32 wJustify )
  1288. *
  1289. *  Description
  1290. *
  1291. *     adds new item field w/string
  1292. *
  1293. *  Parameters
  1294. *
  1295. *        Type           Description
  1296. *        --------------------------
  1297. *        sInstance      pointer to an .ini instance
  1298. *        szItem         pointer to item string
  1299. *        szString       pointer to string 
  1300. *        wJustify       width of field
  1301. *
  1302. *  Return
  1303. *
  1304. *     _TRUE    item and string added
  1305. *     _FALSE   item not added, not enough memory, etc..
  1306. *
  1307. ****************************************************************************/
  1308. BOOL    cdecl    hmiINIAddItemString( _INI_INSTANCE * sInstance, PSTR szItem, PSTR szString, W32 wJustify )
  1309.     {
  1310.       PSTR  pDataPtr;
  1311.       W32  wSize;
  1312.  
  1313.       // check if item exists
  1314.       if ( hmiINILocateItem( sInstance, szItem ) )
  1315.       {
  1316.          // alter string
  1317.          hmiINIWriteString( sInstance, szString );
  1318.  
  1319.          // return success
  1320.          return( _TRUE );
  1321.       }
  1322.  
  1323.       // get data pointer
  1324.       pDataPtr    =  sInstance->pCurrent;
  1325.  
  1326.       // adjust size to account for item, =, SPACE, STRING, CR/LF
  1327.       wSize       =  wJustify + 4 + strlen( szString );
  1328.  
  1329.       // check if there is room to add item/string
  1330.       if ( sInstance->wSize + wSize > sInstance->wMaxSize )
  1331.          return( _FALSE );
  1332.  
  1333.       // make room in memory
  1334.       memmove( pDataPtr + wSize, pDataPtr, ( sInstance->pData + sInstance->wSize ) - pDataPtr );
  1335.  
  1336.       // copy in new item string
  1337.       while( *szItem )
  1338.       {
  1339.          // copy in character into .ini
  1340.          *pDataPtr++ =  *szItem++;
  1341.  
  1342.          // decrement justify characters
  1343.          wJustify--;
  1344.       }
  1345.  
  1346.       // fill in the rest of the white space to 
  1347.       // justify item
  1348.       while( wJustify-- )
  1349.          *pDataPtr++ =  _INI_SPACE;
  1350.  
  1351.       // fill in the = sign and an extra space
  1352.       *pDataPtr++    =  _INI_EQUATE;
  1353.       *pDataPtr++    =  _INI_SPACE;
  1354.  
  1355.       // copy in the string
  1356.       while( *szString )
  1357.          *pDataPtr++ =  *szString++;
  1358.  
  1359.       // add in CR/LF
  1360.       *pDataPtr++    =  _INI_CR;
  1361.       *pDataPtr++    =  _INI_LF;
  1362.  
  1363.       // adjust size
  1364.       sInstance->wSize     += wSize;
  1365.  
  1366.       // set the modified flag
  1367.       sInstance->wFlags    |= _INI_MODIFIED;
  1368.  
  1369.       // return success
  1370.       return( _TRUE );
  1371.  
  1372.     }
  1373.  
  1374. /****************************************************************************
  1375. *
  1376. *  Syntax
  1377. *
  1378. *     BOOL    cdecl    hmiINIAddItemDecimal( _INI_INSTANCE * sInstance, PSTR szItem, 
  1379. *                                      W32 wValue, W32 wJustify, W32 wRadix )
  1380. *
  1381. *  Description
  1382. *
  1383. *     adds new item field w/decimal
  1384. *
  1385. *  Parameters
  1386. *
  1387. *        Type           Description
  1388. *        --------------------------
  1389. *        sInstance      pointer to an .ini instance
  1390. *        szItem         pointer to item string
  1391. *        wValue         value to write out
  1392. *        wJustify       width of field
  1393. *        wRadix         radix (base) of field
  1394. *
  1395. *  Return
  1396. *
  1397. *     _TRUE    item and string added
  1398. *     _FALSE   item not added, not enough memory, etc..
  1399. *
  1400. ****************************************************************************/
  1401. BOOL    cdecl    hmiINIAddItemDecimal(   _INI_INSTANCE * sInstance,
  1402.                                     PSTR  szItem, 
  1403.                                     W32  wValue, 
  1404.                                     W32  wJustify,
  1405.                                     W32  wRadix )
  1406.     {
  1407.       PSTR  pDataPtr;
  1408.       W32  wSize;
  1409.       W32  wIndex;
  1410.       BYTE  szBuffer[ 32 ];
  1411.  
  1412.       // check if item exists
  1413.       if ( hmiINILocateItem( sInstance, szItem ) )
  1414.       {
  1415.          // alter string
  1416.          hmiINIWriteDecimal( sInstance, wValue );
  1417.  
  1418.          // return success
  1419.          return( _TRUE );
  1420.       }
  1421.  
  1422.       // convert decimal to string
  1423.       if ( wRadix == 16 )
  1424.       {
  1425.          // add hex '0x' preceeding value
  1426.          szBuffer[ 0 ]  =  '0';
  1427.          szBuffer[ 1 ]  =  'x';
  1428.  
  1429.          // convert to hex
  1430.          itoa( wValue, (PSTR)&szBuffer[ 2 ], 16 );
  1431.       }
  1432.       else
  1433.          itoa( wValue, (PSTR)&szBuffer[ 0 ], 10 );
  1434.  
  1435.       // get data pointer
  1436.       pDataPtr    =  sInstance->pCurrent;
  1437.  
  1438.       // adjust size to account for item, =, SPACE, STRING, CR/LF
  1439.       wSize       =  wJustify + 4 + strlen( ( char const * )szBuffer );
  1440.  
  1441.       // check if there is room to add item/string
  1442.       if ( sInstance->wSize + wSize > sInstance->wMaxSize )
  1443.          return( _FALSE );
  1444.  
  1445.       // make room in memory
  1446.       memmove( pDataPtr + wSize, pDataPtr, ( sInstance->pData + sInstance->wSize ) - pDataPtr );
  1447.  
  1448.       // copy in new item string
  1449.       while( *szItem )
  1450.       {
  1451.          // copy in character into .ini
  1452.          *pDataPtr++ =  *szItem++;
  1453.  
  1454.          // decrement justify characters
  1455.          wJustify--;
  1456.       }
  1457.  
  1458.       // fill in the rest of the white space to 
  1459.       // justify item
  1460.       while( wJustify-- )
  1461.          *pDataPtr++ =  _INI_SPACE;
  1462.  
  1463.       // fill in the = sign and an extra space
  1464.       *pDataPtr++    =  _INI_EQUATE;
  1465.       *pDataPtr++    =  _INI_SPACE;
  1466.  
  1467.       // reset index
  1468.       wIndex   =  0;
  1469.  
  1470.       // copy in the string
  1471.       while( szBuffer[ wIndex ] )
  1472.          *pDataPtr++ =  szBuffer[ wIndex++ ];
  1473.  
  1474.       // add in CR/LF
  1475.       *pDataPtr++    =  _INI_CR;
  1476.       *pDataPtr++    =  _INI_LF;
  1477.  
  1478.       // adjust size
  1479.       sInstance->wSize     += wSize;
  1480.  
  1481.       // set the modified flag
  1482.       sInstance->wFlags    |= _INI_MODIFIED;
  1483.  
  1484.       // return success
  1485.       return( _TRUE );
  1486.  
  1487.     }
  1488.  
  1489. /****************************************************************************
  1490. *
  1491. *  Syntax
  1492. *
  1493. *     W32    hmiINIHex2Decimal( PSTR szHexValue )
  1494. *
  1495. *  Description
  1496. *
  1497. *     Converts passed number to hex
  1498. *
  1499. *  Parameters
  1500. *
  1501. *        Type           Description
  1502. *        --------------------------
  1503. *        szHexValue     pointer to the string containing hex value
  1504. *
  1505. *  Return
  1506. *
  1507. *     decimal value of hex number
  1508. *
  1509. ****************************************************************************/
  1510. W32    hmiINIHex2Decimal( PSTR szHexValue )
  1511.     {
  1512.       W32  wDecimal    =  0;
  1513.       W32    wPlaces     =  strlen( szHexValue );
  1514.       W32    wMultIndex;
  1515.       W32    wIndex      =  0;
  1516.  
  1517.         // count down
  1518.       do
  1519.          {
  1520.             // accumulate value
  1521.             wDecimal += wMultiplier[ wPlaces - 1 ] * hmiINIGetHexIndex( (BYTE)szHexValue[ wIndex++ ] );
  1522.  
  1523.             // decrement places
  1524.             wPlaces--;
  1525.          }
  1526.       while( wPlaces > 0 );
  1527.  
  1528.       // return decimal
  1529.       return( wDecimal );
  1530.     }
  1531.  
  1532. /****************************************************************************
  1533. *
  1534. *  Syntax
  1535. *
  1536. *     W32    hmiINIGetHexIndex( BYTE bValue )
  1537. *
  1538. *  Description
  1539. *
  1540. *     Get the index of a hex character
  1541. *
  1542. *  Parameters
  1543. *
  1544. *        Type           Description
  1545. *        --------------------------
  1546. *        bValue         value to located
  1547. *
  1548. *  Return
  1549. *
  1550. *     index into table of hex value
  1551. *
  1552. ****************************************************************************/
  1553. W32    hmiINIGetHexIndex( BYTE bValue )
  1554.     {
  1555.         W32    wIndex;
  1556.  
  1557.       // search
  1558.       for ( wIndex = 0; wIndex < 16; wIndex++ )
  1559.          if ( szHexNumbers[ wIndex ] == toupper( bValue ) )
  1560.             return( wIndex );
  1561.  
  1562.       // error return
  1563.       return( -1 );
  1564.     }
  1565.